Repository navigation
Plan history: show the latest finished slot, and stop the false 'stale' warning - #5414
Open
chalfontchubby wants to merge 4 commits into
Open
chalfontchubby wants to merge 4 commits into
chalfontchubby wants to merge 4 commits into
Conversation
…ss by each view's own refresh interval The plan page's History view is built by calculate_yesterday() from what actually happened, at most once every 59 minutes. The live Plan view starts at the current slot, so the slots finished since the last rebuild showed in neither view: at 21:35 the History stopped at 20:30 and the Plan started at 21:30. And the page judged every view against the live plan's 15-minute stale limit, so on the History view it warned "Plan data is stale" for about 45 minutes of every hour although nothing was wrong. - calculate_yesterday() now rebuilds once per completed plan slot (plan_interval_minutes), on the first re-plan at least one run (5 minutes) after the slot ends, so the boundary run's own cost_today write is recorded before its history is read back. A rebuild takes 0.4-0.9 s on a live install; at the default 30-minute slots that is 48 a day instead of 24 (before #2913 it ran on every re-plan, about 144). - Each dataset the page shows carries refresh_minutes, the longest Predbat should take to republish it (the live plan: calculate_plan_every; the plan history: a slot, the run it waits and a re-plan interval). The page warns a run after that, never under 15 minutes, against the data the current view shows, and hides the warning when the view has no data. At the defaults: Plan 15 minutes (as before), History 50. Trade-offs, kept: with calculate_plan_every at or above the slot length, re-plans can fall on slot boundaries and the rebuild then happens there; cost_yesterday and savings_yesterday_* roll over at the first re-plan after 00:05 rather than at 00:00; cost_yesterday/savings_yesterday_predbat, with their large html/json attributes, are written twice as often. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
history_slot() and history_refresh_minutes() wait one run past a slot boundary, and their docstrings call that run PREDICT_STEP. One run is RUN_EVERY in const.py; PREDICT_STEP is the prediction step. Both are 5 today, so nothing changes now, but if either changed the wait would quietly be wrong. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The slot key can skip the repeated daylight-saving hour, leaving History incomplete and falsely stale.
1 open finding
What changed in this PR
Updates plan history after each completed slot and applies view-specific stale-data thresholds, refining the hourly cadence introduced by #2913.
Changes:
- Rebuilds history per completed plan slot.
- Adds refresh metadata and per-view stale checks.
- Expands history and renderer test coverage.
| File | Description |
|---|---|
apps/predbat/output.py |
Adds slot-based rebuilding and refresh metadata. |
apps/predbat/web.py |
Generalizes stale-warning text. |
apps/predbat/web_helper.py |
Implements per-view staleness handling. |
apps/predbat/unit_test.py |
Registers the new renderer test. |
apps/predbat/tests/test_plan_staleness_js.py |
Tests stale-warning JavaScript structure. |
apps/predbat/tests/test_calculate_yesterday.py |
Tests slot cadence and refresh metadata. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…as separate slots history_slot() keyed slots by local date and wall-clock slot only, so the first and second 01:35 on the night the clocks go back collapsed to one key. With an hourly re-plan the second run was skipped and the History view went two hours without a rebuild, past its advertised refresh interval. Add the UTC offset to the key, and step back the one run in UTC rather than on the wall clock, so the step lands on the right side of the change (pytz keeps the old offset on wall-clock arithmetic; zoneinfo drops fold). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The one-run wait counts the 00:00 run towards the last slot of the day before, so when the previous rebuild was already in that slot the forced midnight re-plan skipped it. With an hourly re-plan, cost_yesterday and the savings_yesterday sensors went on showing the day before yesterday until 01:00; main rebuilt at 00:00 because the date had changed. Rebuild whenever the local date has changed as well as when the slot has. Also correct a test comment that still called the schedule hourly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Posted by Claude on behalf of @chalfontchubby.
Summary
The web page's Plan → History view had two problems:
With this change History is rebuilt once per completed slot, so the last finished slot shows within one or two re-plans of ending. Each view is judged against how often it is actually republished, so the warning only appears when something has really stopped.
Detail
Rebuild cadence:
calculate_yesterday()plan_interval_minutes), on the first re-plan at least one run (5 minutes) after the slot ends. The wait is so that the boundary run's ownpredbat.cost_todaywrite is already recorded when its history is read back. The key ishistory_slot(): a (date, slot number, UTC offset), stepped back one run in UTC. The offset keeps the hour that repeats when the clocks go back as two separate slots.cost_yesterdayandsavings_yesterday_*on to the day just ended at 00:00.RUN_EVERY(the run cadence), notPREDICT_STEP.Stale warning:
get_plan_renderer_js()refresh_minutes, the longest Predbat should take to republish it:calculate_plan_every, set only when the plan is publishedcurrentViewData()), and the "no data yet" text no longer says "about once an hour".Trade-offs, accepted
calculate_plan_everyat or above the slot length, re-plans can fall on slot boundaries, and the rebuild then happens on the boundary run.cost_yesterdayandsavings_yesterday_predbat, which have large html/json attributes, are written twice as often.savings_total_*) add the figures from the last rebuild before them. That is now about 00:40 at the defaults, not about 01:00, so late cloud load/PV data has about 40 minutes rather than an hour to land before it is counted.Tests
test_calculate_yesterday:refresh_minuteson the published History and baseline data"{}"(a string) wherepublish_html_planandplan_write_debugreturn a dict. They now match the real functions.test_plan_staleness_js: structural checks on the page script (the per-view data, the limit arithmetic, hiding the warning without data, no remaining bare-timestamp checks). It fails on main's script../run_all --quickpass. The rendered page script passesnode --check.🤖 Generated with Claude Code